#ifndef _FILE_INDEX_H_
#define _FILE_INDEX_H_

#include "crossplat_def.h"
#include <time.h>
#include <list>
#include <map>
#include <vector>
#include "scsi_dev.h"
#include "rec_write.h"
#include "serial_file_base.h"
#include "cross_com.h"
using namespace std;
typedef map<int,REC_FILE_LIST>  MAP_CH_FILE_T;

#define  STFS_ONE_RECFILE         1
#define  STFS_MAX_RECSN          0xFFFFFFFF
typedef struct _MAPIDX_KEY_
{
	int64_t	    startTime;		//��ʼʱ��
	uint32_t	idxNO;			//�������
	_MAPIDX_KEY_(uint32_t idxNO, int64_t startTime);
	_MAPIDX_KEY_ & operator=(const _MAPIDX_KEY_ &key1);
	bool operator ==(const _MAPIDX_KEY_ &key1);
	bool operator <(const _MAPIDX_KEY_ & key1) const;
}MAPIDX_KEY,* PMAPIDX_KEY;



typedef list<uint32_t> LIST_INDEX;
typedef map<uint32_t, REC_WRITE_INFO> MAP_WRITEINFO;
typedef map<uint32_t, int64_t>	      MAP_LAST_RECLASTTM;
typedef map<MAPIDX_KEY, STFS_RECIDX_BASEINFO>::iterator MAP_BASEINFO_IT;
//CFile_Idx;
class CFileIndex
{
public:
	CFileIndex();
	~CFileIndex();

	static int Create(CDisk_Dev * dev, uint64_t baseLBA,uint64_t baseRecFileLBA,uint32_t recSizeMB,uint32_t indexInfoSize, int indexNum);
	static int Rebuild(CDisk_Dev * dev,uint64_t baseRecLBA, uint64_t baseIdxLBA,uint32_t recSizeMB,uint32_t indexInfoSize, int indexNum);
	static int CreateComFile(const char* storage_path,uint64_t baseLBA,uint32_t baseRecFileLBA,uint32_t recSizeMB,uint32_t indexInfoSize, int indexNum);

	int  Open(int diskIndex,char* storageName,uint64_t baseLBA,int defNum = 0,bool bReOpen = false);
	int  OpenByName(int diskIndex,char* devName,uint64_t baseLBA);

	void Close();
#ifdef _WIN32
	int Reset();
#endif

	int ReInit();		//��������������Ϣ
	int InitBuf();     //��ʼ������

	//��ȡ��һ��¼���ļ��������
	int GetNextRecIndex(int * pLeafNum =NULL);

	//֪����һ��¼���������ţ��������ѵ��ģ�
	int GetStartRecIndex(int * pLeafNum = NULL);

	//ѭ��¼�����¼���ļ�
	int GetCycleIndex(uint32_t channel,int dataSrcType,unsigned short & diskIndex, uint32_t & indexNo);

    int SearchCycleSNIdx(MAP_BASEINFO_IT & leastIt,uint32_t & leastSN);

	int SearchLeastSN(uint32_t & leastSN);
	int RecountLeastSN();
	int RepairRecord(int max_cnt = 4);
	//�޸�¼���ļ�
	int RepairRecFile(int indexNo);

	int GetUnfinishedIndex(int ch,REC_FILE_INFO & recFile);
	int ClearUnfinishedIndex();
#ifdef _WIN32
	int  GetNextReplayIndex(int * pLeafNum = NULL);
#endif
	int RecordStart(REC_FILE_INFO & recordInfo);
	int RecordEnd(REC_FILE_INFO & recInfo);
	int RecordReInit(REC_FILE_INFO & recInfo);
	int RecordChange(REC_FILE_INFO & recordInfo);
	//��������������
	int LockFile(REC_FILE_INFO & recordInfo);
	int UnlockFile(REC_FILE_INFO & recordInfo);

	int DeleteFile(REC_FILE_INFO & recordInfo);
	int DeleteOldFile(int channel, const int64_t & oldTime);

	int ResetIndex(uint32_t indexNo);
#ifdef _WIN32
	int ResetIndexALL();
#endif
 	
	//����¼���ļ�
	
	int SearchDayOfMonth(int64_t tmStart,int64_t tmEnd,int recType,vector<int32_t>& vecDayBIT);

	//搜索录像文件
	int SearchFileTag(char* tag, int tag_len, int64_t tmStart, int64_t tmEnd,vector<uint8_t>& vecCH,
		uint32_t maxNum, MAP_CH_FILE_T& mapPerChFile, int recType =-1, bool bForward = true);

	int SearchFile(int64_t tmStart, int64_t tmEnd,int recType, vector<uint8_t>& vecCH,
		uint32_t maxNum,MAP_CH_FILE_T& mapPerChFile,bool bForward = true);
	int SearchFileOneCH(int ch,int64_t tmStart, int64_t tmEnd,int recType,
		uint32_t maxNum,REC_FILE_LIST& filelst);
	int SearchRecAllDay(VEC_REC_DAY_T & vecRecDay);
	int SearchRecByIndex(uint32_t indexNO,vector<REC_FILE_INFO> vecRec);

	void AddToRepairList(REC_FILE_INFO & file);
	static void AddToFileList(list<REC_FILE_INFO> & list, REC_FILE_INFO & index,uint32_t maxNum, uint32_t orderType,int64_t tmStart= 0, int64_t tmEnd = 0);
	//���ϲ�¼���ļ�����
	static void AddToFileListMerger(list<REC_FILE_INFO> & list, REC_FILE_INFO & index,uint32_t maxNum, uint32_t orderType);

	static int MarkDateOfMonth(int32_t & dateBit,int64_t monthStart,int64_t tmStart,int64_t tmEnd);
	int RegisterRecWriter(int ch, CRecWriteBase * pRec);

	int DestroyRecWriter(int ch);
	CRecWriteBase* GetCurRecWriter(int ch ,uint32_t fileIndex);

	int GetFileSize(uint32_t & fileSize, REC_FILE_INFO &recordInfo, int64_t startTime, int64_t endTime);


	int	SearchFileMapInOldIndex(int64_t tmStart, int64_t tmEnd,int recType, vector<uint8_t>& vecCH,
		uint32_t maxNum,MAP_CH_FILE_T& mapPerChFile,bool bForward);
	int SearchFileMapInOldIndex1CH(int64_t tmStart, int64_t tmEnd,int recType, int channel,
		uint32_t maxNum,REC_FILE_LIST& fileList);

	int	SearchFileLstInOldIndex(int64_t tmStart, int64_t tmEnd,int recType, vector<uint8_t>& vecCH,
		uint32_t maxNum,REC_FILE_LIST& fileList);

	int SearchMpAllIndex(REC_FILE_LIST & fileLst,int chBIT = -1);
	int SearchMpDSTIndex(REC_FILE_LIST & fileLst);
	int SearchUnfinishedIndex(REC_FILE_LIST & fileLst);
	void GetLastTmMp(MAP_LAST_RECLASTTM & mpLast,MAP_CH_FILE_T& mapPerChFile);
	void GetLastTmList(int64_t & dstJumpTm,REC_FILE_LIST& fileList);
	int GetRecordSegSize(STFS_RECIDX_BASEINFO	*pIndex);
	bool IsRecording(STFS_RECIDX_BASEINFO	*pBaseInfo);
	bool IsRecLocked(STFS_RECIDX_BASEINFO	*pBaseInfo);
	int  MergerRecord(uchar_t * indexBuf);
	int GetMaxTime(int64_t & recTm);
	int GetFarthestTime(int64_t& recTm, char * device_sn = NULL);
	int GetLastDevSn(char* dev_sn, int sz_len);
	uint32_t GetNextRecordSN();
	int GetFileSaveIndex();
	uchar_t * CreateSearchBuf(int & bufSize, int idxNum, const int dfSize);
	int  GetSearchReadSize(uint32_t & baseIndexNO, int bufSize, STFS_RECIDX_BASEINFO* pBaseInfo);
	CSerialFileBase * GetIndexFile()
	{
		return m_pFile;
	}

	static uint32_t MAX_CHANNEL;
	static int MAX_UNFINISHED_NUM;
	static uchar_t * SEARCH_BUF;
protected:
	bool SearchFile1CHRecording(int ch ,int64_t tmStart, int64_t tmEnd,int recType,
		uint32_t maxNum,REC_FILE_LIST& filelst,bool orderType,REC_WRITE_INFO * pRecInfo);
	bool SearchFile1CHRecordingTag(char* tag, int tag_len, int ch, int64_t tmStart, int64_t tmEnd, int recType,
		uint32_t maxNum, REC_FILE_LIST& filelst, bool orderType, REC_WRITE_INFO* pRecInfo);
	//¼����������������Ϣ
	void SetIdxBaseInfo(INDEX_INFO_HEAD * pIdxHead,REC_FILE_INFO & recordInfo);

	//¼�����Ϣ
	void SetRecSegInfo(REC_SEGMENT_S * pSegInfo,REC_FILE_INFO & recordInfo);

	void GetOneReocrdFile(REC_FILE_INFO & recFile,STFS_RECIDX_BASEINFO * pBaseInfo);
	void GetSegRecordFile(REC_FILE_INFO & recFile,STFS_RECIDX_BASEINFO * pBaseInfo,int segIdx,REC_SEGMENT_S * pSeg);

	void GetOneRecordFileRecording(REC_FILE_INFO & recFile,STFS_RECIDX_BASEINFO * pBaseInfo,CRecWriteBase * pRecWriter);
	void GetSegRecordFileRecording(REC_FILE_INFO & recFile,STFS_RECIDX_BASEINFO * pBaseInfo,int segIdx,REC_SEGMENT_S * pSeg,CRecWriteBase * pRecWriter = NULL);

	uint32_t GetIndexOffset(int indexNo)
	{
		return m_indexInfoOffset + indexNo * m_perIdxLen;
	}
	
	bool IsContextSearch(REC_SEGMENT_S & segInfo,int  recordType, int index = 0, int segidx = 0);
	
	bool IsNeedMerger(REC_FILE_INFO & curRecInfo,PREC_SEGMENT_S  pLastSeg);
	bool IsEffectRecordSeg(uint32_t indexNO,int64_t tmStart, int64_t tmEnd, uint32_t totalSize);
	void CreateRecordSN(uint32_t & recordSN);
	void GetRecTimeArea(int64_t tmStart,int64_t tmEnd);
	
public:
	map<MAPIDX_KEY, STFS_RECIDX_BASEINFO> m_index;		//¼�������map
	map<int, CRecWriteBase*> m_mpRecording;				//ÿ��ͨ�� ����¼����ļ�
	MAP_WRITEINFO m_mpRecInfo;
	static char st_device_sn[24];					//设备SN
	static bool st_show_log;                        //是否显示日志                        
protected:

	char        m_filename[40];		                //ͨ���ļ���
	CDisk_Dev	*m_pDev;							//������Ӳ���豸
	//CSerial_file* m_pFile;						//�ļ�����ָ��
	CSerialFileBase* m_pFile;	                    //�ļ�����ָ��
	bool        m_bOpen;							//�ļ��Ƿ��Ѿ���
	uint16_t    m_diskIndex;						//���̱��

	uint64_t	m_fileBaseLBA;						//��һ����¼���ļ�������
	uint64_t	m_idxLBA;							//������LBA
//	uint64_t    m_indexInfoLBA;						//����������LBA
	uint64_t    m_dstJumpTime;						//��������ʱ��

	uint32_t    m_maxIdx;							//���������š�
	uint32_t    m_recFileSize;						//�����ļ��Ĵ�С
	uint32_t    m_fileSize;							//�����ļ���С

	uint32_t	m_indexInfoOffset;					//�洢��������Ϣƫ��λ��
	uint32_t	m_perIdxLen;						//ÿ�����鳤��

	uint32_t	m_indexInfoBaseLen;					//ÿ���洢����������������Ϣ
	//¼�����Ϣ
	uint32_t	m_segInfoOffset;					//�ļ���¼����ڶ�Ӧ��������Ϣƫ��λ��
	uint32_t	m_recSegInfoLen;					//ÿ���ļ���¼��x���ȣ����ڼ��ݲ�ͬ�ؽṹ�壩
	uint32_t	m_recSegInfoNum;					//Ԥ���洢�ռ��д�ļ�¼��Ŀ���ļ���¼��
	uint32_t    m_LastUseIdx;						//���һ������ʹ�õ�������

	LIST_INDEX  m_invalidIndexList;					//m_unUsed_index			//δʹ�ã����õ��������
	REC_FILE_LIST  m_unfinishedIndexList;				//�������رյ��ļ�����Ҫ���޸����ļ�

	LIST_INDEX  m_lst_done_idx;							//�Ѿ�¼��õ�����

								//д���״̬��Ϣ

	map<MAPIDX_KEY,STFS_RECIDX_BASEINFO> m_dstRecIndex; //ר���ڴ洢ʱ�������������¼
	CCross_Lock	 m_lock;

	uint32_t     m_recordSN;                             //¼������к�
	uint32_t     m_leastSN;                              //��С�����к�
	uint32_t	 m_sptChBit;                             //֧�ֵ�ͨ��λ
	uint32_t     m_lock_percent;                        //�����ٷֱ�
public:
	void Lock()
	{
		m_lock.Lock();
	}
	void Unlcok()
	{
		m_lock.UnLock();
	}
	uint32_t GetMaxIndex()
	{
		return m_maxIdx;
	}
	uint32_t GetInfoLen()
	{
		return m_perIdxLen;
	}
	uint32_t GetSegInfoOffset()
	{
		return m_segInfoOffset;
	}
	int GetRecordNum()
	{
		return (int)m_index.size();
	}

	int64_t GetCurDSTJumpTime()
	{
		return m_dstJumpTime;
	}
	CDisk_Dev * GetDev()
	{
		return m_pDev;
	}
 	char * get_device_name()
	{
		return m_filename;
	}
	int GetDiskIndex()
	{
		return m_diskIndex;
	}
	uint32_t GetIdxOffset(uint32_t  indexNO )
	{
		return 	m_indexInfoOffset + indexNO * m_perIdxLen;
	}
	uint32_t GetRecSegOffset(uint32_t & indexNO, int & seg)
	{
		return 	m_indexInfoOffset + indexNO * m_perIdxLen + m_segInfoOffset + seg * m_recSegInfoLen;
	}
	bool IsOpened()
	{
		return	m_bOpen;
	}

	LIST_INDEX* GetIdxList()
	{
		return &m_invalidIndexList;
	}

	int  GetLeafSize()
	{
	    m_lock.Lock();
		int ret = (int)m_invalidIndexList.size();
        m_lock.UnLock();
        return ret;
	}

	uint64_t GetBaseLBA()
	{
		return m_fileBaseLBA;
	}

	uint32_t GetRecFileSize()
	{
		return m_recFileSize;
	}

	uint32_t GetMaxIndexNum()
	{
		return	m_maxIdx;
	}

	uint32_t GetIndexFileSize()
	{
		return m_fileSize;
	}

	int GetDoneNum()
	{
		return (int)m_lst_done_idx.size();
	}

	int GetRecordingNum()
	{
	     m_lock.Lock();
		int ret = (int)m_mpRecording.size();
		 m_lock.UnLock();
        return ret;
	}

	int GetUnfinishedNum()
	{
	     m_lock.Lock();
		 int ret = (int)m_unfinishedIndexList.size();
		 m_lock.UnLock();
         return ret;
	}
	int GetUnfinishedNum(int ch);

	int GetSegInfoNum()
	{
		return m_recSegInfoNum;
	}

	int GetCurRecordSN()
	{
		return m_recordSN;
	}

	void SetDiskIndex(int diskIndex)
	{
		m_diskIndex = diskIndex;
	}

	void SetSptChBit(uint32_t chBit)
	{
		m_sptChBit = chBit;
	}

	uint32_t GetSptChBit()
	{
		return m_sptChBit;
	}

};
#define STFS_RECORD_INDEX_FILE "recindex.bin"
#endif //_FILE_INDEX_H
